#include <iostream>
#include <cerrno>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

using namespace std;

int main(int argv, char* argc[])
{
    if(argv != 2)
    {
        cout << "Useage: \n\t" << "server_port" << endl;
        return -1;
    }
    //1.创建套接字
    int sock = socket(AF_INET, SOCK_DGRAM, 0);

    if(sock < 0)
    {
        cerr << "socket create error: " << errno << endl;
        return 1;
    }
    //2. 给该服务器绑定端口号和ip(特殊处理)
    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argc[1]));//此处的端口号，是我们计算机的变量，是主机序列
    //a.需要将人识别的点分十进制，字符串风格IP地址，转化为4字节整数IP
    //b.也要考虑大小端
    //in_addr_t inet_addr(const char *cp);能完成上面ab两个工作
    //云服务器，不允许用户直接bind公网IP，另外，实际正常编写的时候，我们也不会指明IP
    //in_addr_t inet_addr("127.0.0.1")//点分十进制，字符串风格
    //INADDR_ANY：如果你bind的是确定的IP（主机），一位置只有发到该IP主机上的数据
    //才会交给你的网络进程，但是，一般服务器有多张网卡，配置多个IP，我们需要的不是将某个IP上面的数据，我们需要的是，所有发送到主机，发送到该端口的数据。
    local.sin_addr.s_addr = INADDR_ANY;

    if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0)
    {
        cerr << "bind error: " << errno << endl;
        return 2;
    }

    //3.提供服务
    bool quit = false;
    #define NUM 1024
    char buffer[NUM];
    while(!quit)
    {
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer); 

        ssize_t cnt = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr*)&peer, &len);
        if(cnt > 0)
        {
            buffer[cnt] = 0;
             FILE* fp = popen(buffer, "r");
            string echo_hello = buffer;
             char line[1024] = {0};
             while(fgets(line, sizeof(line), fp) != nullptr)
             {
                echo_hello += line;
             }
            cout << "client# " << buffer << endl;
            //根据用户输出，构建一个新的返回字符串
            //echo_hello += "...";
            sendto(sock, echo_hello.c_str(), echo_hello.size(), 0, ( struct sockaddr*)&peer, len);
        }
        else
        {
            //TODO
        }
    }

    return 0;
}